//////////////
//点灯
#include <ArduinoJson.h>
#include <ArduinoJson.hpp>

#define BLINKER_WIFI

#include <Blinker.h>

char auth[] = "88cab9f2b44c";
char ssid[] = "000";
char pswd[] = "66668888";
//数据
BlinkerNumber Number1("num-ab");
BlinkerNumber Number2("num-cd");
BlinkerNumber Number3("num-ef");
BlinkerNumber Number4("num-gh");
BlinkerNumber Number5("num-ij");
BlinkerNumber Number6("num-kl");
BlinkerNumber Number7("num-mn");
BlinkerNumber Number8("num-op");
BlinkerNumber Number9("num-qr");

BlinkerNumber Number10("num-h");
BlinkerNumber Number11("num-t");
//滑块
BlinkerSlider Slider1("ran-key");
BlinkerSlider Slider2("ran-min");
BlinkerSlider Slider3("ran-max");
//按键
BlinkerButton Button1("btn-open");
BlinkerButton Button2("btn-res");
//文本显示
BlinkerText Text1("tex-pc");
BlinkerText Text2("tex-ard");
BlinkerText Text3("tex-bl");
BlinkerText Text4("tex-dht");
BlinkerText Text5("tex-key");
const char* time1;
int year1,month1,day1 , yday1,wday1,hour1, min1,sec1;

////////////
//////////////
//风扇
int mins=25;
int maxs=80;//设定温度的上限和下限
#define fensanio 2 //定义风扇引脚
//////////////
/////////////
//温湿度
#include "DHT.h"
#define DHTPIN 5  // 定义DHT11数据引脚连接到ESP32的GPIO17
#define DHTTYPE DHT11   // 定义传感器类型为DHT11
DHT dht(DHTPIN, DHTTYPE);  // 创建DHT传感器对象
float h ;
float t ;
//////////////
//////////////
//oledu8g2
#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0,SCL,SDA,U8X8_PIN_NONE);
////////////////
////////////////
//软件线程
unsigned long previousBlinkTime;
int blinkInterval = 500; //设置延迟xxxms执行程序
unsigned long previousBlinkTime1;
int blinkInterval1 = 1000; //设置延迟xxxms执行程序
////////////////
////////////////
//按键任务
int k=-1;//等于-1是为了开机自启检验
#define ioo 4  //任务数等于 x+1
////////////
///////////
#define open 15 //定义开机引脚
#define res 16//定义开机引脚
#define PCio 17//监控电脑是否启动引脚
///////////
////////////
//arda64标志
int ab,cd,ef,gh,ij,kl,mn,op,arda;
float qr;

/////////
/////////
//自检标志位
int ard;//arda64标志位
int PC;
int ardbl;//arda64传给服务器的标志位
/////////
////////////
//函数定义
void dhtoled ();//温湿度显示
void dhtwd ();//获取温湿度
void time();//定时初始化
void millisBlink(unsigned long currentTime);//定时中断函数1
void millisBlink1(unsigned long currentTime);//定时中断函数2
void keyinit();//按键初始化
void keyl ();//按键左中断
void keyr ();//按键右中断
void arda64();//arda64信息获取
void arda64init ();//arda64标志位初始化
void arda64oledW ();//arda64读取处理器温度显示
void arda64oled();//arda64读取处理器信息显示
void ShowText(void);//屏幕初始化
void appinit();//点灯科技初始化
void app();//点灯科技反馈按键键值
void ntpinit ();//点灯科技时间
void ntp ();//显示时间
void fensaninit ();//风扇引脚初始化
void fensan();//风扇识别
void pwrinit();//主机启动按键初始化
void pwropen();//开机按键
void pwrres ();//重启按键
void PCOPbl ();//上报自检数据
void post ();//自检数据
//////////
//////////
//主函数
void setup(void) 
{
  ShowText( );//屏幕初始化
  keyinit();//按键初始化
  dht.begin(); //温湿度初始化
  Serial.begin(9600);  //串口初始化
  appinit(); //软件初始化
  fensaninit ();//风扇初始化
  pwrinit();//服务自检初始化
  PCinit ();//服务器启动自检初始化
}

void loop(void) 
{ 
  Blinker.run();
  time();
  //app();
  arda64init ();
  fensan ();
  if(k==-1)
  {
    post();
  }
  if(k==0)
  {
   arda64oled();
  }
  if(k==1)
  {
   arda64oledW ();
  }
  if (k==2)
 {
  dhtoled ();  
 }
 if (k==3)
 {
  ntp ();
 }
 if (k==4)
 {
  post ();
 }
}
////////////////////////
////////////////////////
//定时
void time()
{
 unsigned long currentMillis = millis(); // 获取当前时间
millisBlink(currentMillis);//调用函数
millisBlink1(currentMillis);//调用函数
}

void millisBlink(unsigned long currentTime) { 
//检查是否到达时间间隔
if (currentTime - previousBlinkTime >= blinkInterval) {    //如果时间间隔达到
//执行代码区
PCOP ();
arda64();
dhtwd ();
ntpinit ();
//执行代码区
    previousBlinkTime = currentTime;  // 将检查时间复位           
}  else if (currentTime - previousBlinkTime <= 0) {   // 如果millis时间溢出
    previousBlinkTime = currentTime;
}
}

void millisBlink1(unsigned long currentTime) { 
//检查是否到达时间间隔
if (currentTime - previousBlinkTime1 >= blinkInterval1) {    //如果时间间隔达到
//执行代码区
app();
postbl ();
//执行代码区
    previousBlinkTime1 = currentTime;  // 将检查时间复位           
}  else if (currentTime - previousBlinkTime1 <= 0) {   // 如果millis时间溢出
    previousBlinkTime1 = currentTime;
}
}


////////////////////////
/////////////////////////////
//自检
void PCinit ()
{
  digitalWrite(PCio, INPUT_PULLDOWN);

}
void PCOP ()
{
  if (digitalRead(PCio) == 1 )
  {
    PC=1;
  }else { PC=0;}
}

void postbl ()
{
  bool state = Blinker.init();
  if (ardbl == 1)
  {
   Text2.print("arda64服务：成功");
  }else{Text2.print("arda64服务：失败");}
  if (state)
  {
    Text3.print("blinker服务：成功");
  }else{ Text3.print("blinker服务：失败");}
  if (h && t)
  {
    Text4.print("温湿度服务：成功");
  }else{ Text4.print("温湿度服务：失败");}
  if (PC==1)
  {          
    Text1.print("服务器主机：成功");
  }else{ Text1.print("服务器主机服务：失败");}

}

void post ()
{
  int post;
  bool state = Blinker.init();
  u8g2.clearBuffer();  //清除缓存
  u8g2.drawUTF8(0,10,"MCU服务：success");
  if (ard == 1)
  {
    u8g2.drawUTF8(0,20,"arda64服务：success");ardbl=1;post++;
  }else{ u8g2.drawUTF8(0,20,"arda64服务：error");ardbl=0;}
  if (state)
  {
    u8g2.drawUTF8(0,30,"blinker服务：success");post++;
  }else{ u8g2.drawUTF8(0,30,"blinker服务：error");}
  if (h && t)
  {
    u8g2.drawUTF8(0,40,"温湿度服务：success");post++;
  }else{ u8g2.drawUTF8(0,40,"温湿度服务：error");}
  if (PC==1)
  {
    u8g2.drawUTF8(0,50,"服务器主机：success");post++;
  }else{ u8g2.drawUTF8(0,50,"服务器主机：error");}

  if ( k==-1)
  {
      if (post==4)
    {
    //u8g2.drawUTF8(0,60,"自检成功服务启动启动!");
    //u8g2.drawUTF8(0,30,"Ciallo～(∠・ω< )⌒★");
    //u8g2.sendBuffer();
    //unsigned long currentMillis = millis(); // 获取当前时间
    k=0;
    }else {u8g2.drawUTF8(0,60,"自检失败任意按键跳过");}
  }

  if ( k==4)
  {
    if (post==4)
    {
    u8g2.drawUTF8(0,60,"Ciallo～(∠・ω< )⌒★");
    }else {u8g2.drawUTF8(0,60,"自检失败啦  :(");}
  }
  u8g2.sendBuffer();
}



//////////////////////////////////////
/////////////////////
//电源开关
void pwrinit()
{
  pinMode(open,OUTPUT_OPEN_DRAIN);
  pinMode(res,OUTPUT_OPEN_DRAIN);
  digitalWrite(open, 1);
  digitalWrite(res, 1);
}

void pwropen ()
{
  digitalWrite(open, 0);
  delay(100);
  digitalWrite(open, 1);
}

void pwrres ()
{
  digitalWrite(res, 0);
  delay(100);
  digitalWrite(res, 1);
}
/////////////////////
/////////////////////
//风扇

void fensaninit ()
{
pinMode(fensanio,OUTPUT);
}
void fensan ()
{
  if (mins>=maxs)
    {
      mins=maxs;
    }
   if (mn==0)
   {
    analogWrite(fensanio, 255);
   }
   if (mn>0)//保证温控正常才启用温控
   {
    if (mn<mins)
    {
      analogWrite(fensanio, 0);

    }
    if (mn>=mins && mn<=maxs)
    {
     analogWrite(fensanio, 120);
    }
    if (mn>maxs)
    {
     analogWrite(fensanio, 255);
    }
   }
   

}

/////////////////////
//////////////////////
//点灯科技
void button1_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    pwropen();
    
  
}
void button2_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    pwrres();
}

void slider1_callback(int32_t value) //云控制按键页面
{
    BLINKER_LOG("get slider value: ", value);
    k=value;
}
void slider2_callback(int32_t value)
{
    //digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    BLINKER_LOG("get slider value: ", value);
    mins=value;
}
void slider3_callback(int32_t value)
{
    //digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    BLINKER_LOG("get slider value: ", value);
    maxs=value;
}
void ntp ()
{
  char var_buff[100];
u8g2.clearBuffer();
sprintf(var_buff, "今年的第%d天-%s",yday1,time1);
u8g2.drawUTF8(0,10,var_buff); 
sprintf(var_buff, "%d年-%d月-%d日",year1,month1,day1); 
u8g2.drawUTF8(0,30,var_buff); 
sprintf(var_buff, "%d时-%d分-%d秒",hour1,min1,sec1); 
u8g2.drawUTF8(0,50,var_buff); 
u8g2.sendBuffer();
}

void ntpinit ()
{
   //获取时间
   year1 = Blinker.year();
   month1 = Blinker.month();
   day1 = Blinker.mday();
   yday1 = Blinker.yday();
   wday1 = Blinker.wday();
   hour1 = Blinker.hour();
   min1 = Blinker.minute();
   sec1 = Blinker.second();

  switch (wday1) {
    case 0:
      time1 = "星期天";
      break;
    case 1:
      time1 = "星期一";
      break;
    case 2:
      time1 = "星期二";
      break;
    case 3:
      time1 = "星期三";
      break;
    case 4:
      time1 = "星期四";
      break;
    case 5:
      time1 = "星期五";
      break;
    case 6:
      time1 = "星期六";
      break;
  };
}
void appinit()
{
  BLINKER_DEBUG.stream(Serial);
  Blinker.begin(auth, ssid, pswd);
  //滑块
  Slider1.attach(slider1_callback);
  Slider2.attach(slider2_callback);
  Slider3.attach(slider3_callback);
  //按键
  Button1.attach(button1_callback);
  Button2.attach(button2_callback);
  Blinker.setTimezone(8.0);//设置时区
  
}
void app()
{
  Slider1.print(k);//滑块反馈按键值
  Slider2.print(mins);
  Slider3.print(maxs);
}

//////////////////////
//////////////////////
//温湿度
void dhtoled ()
{
char var_buff[100];
u8g2.clearBuffer();
sprintf(var_buff, "环境湿度：%.2f%%RH", h); 
u8g2.drawUTF8(0,10,var_buff); 
sprintf(var_buff, "环境温度：%.2f℃", t); 
u8g2.drawUTF8(0,30,var_buff); 
sprintf(var_buff, "风扇设定最低温度：%d℃", mins); 
u8g2.drawUTF8(0,40,var_buff);
sprintf(var_buff, "风扇设定最高温度：%d℃", maxs); 
u8g2.drawUTF8(0,60,var_buff);     
u8g2.sendBuffer();
}
void dhtwd ()
{
  h = dht.readHumidity();          // 读取湿度
  t = dht.readTemperature();       // 读取温度
  Number10.print(h); 
  Number11.print(t); 
}
////////////////////////
///////////////////////
//按键管理
void keyinit()
{
  pinMode(18, INPUT_PULLUP); //初始化中断io
attachInterrupt(18, keyl, FALLING);//初始化中断
pinMode(19, INPUT_PULLUP); //初始化中断io
attachInterrupt(19, keyr, FALLING);//初始化中断
}

void keyl ()
{
  delayMicroseconds(50000);
  if(digitalRead(18)==0)
  {
   k--;
 if (k < 0)
 {
  k=ioo;
 }
  }
}

void keyr ()
{
    delayMicroseconds(50000);
      if(digitalRead(19)==0)
    {
    k++;
    if (k > ioo)
    {
      k=0;
    }
    }
}
///////////////////////////
void arda64init ()
{
  if (Serial.find("zzz"))
  {
    arda=1;
    ard=1;
  }
}
//arda64
void arda64oledW ()
{
  char var_buff[100];
 u8g2.clearBuffer();
///////////////////////////////
sprintf(var_buff, "CPU 温度: %d ℃", mn); 
u8g2.drawUTF8(0,10,var_buff); 
Serial.println("Incoming Buffer is Clear.");
///////////////////////////////
 sprintf(var_buff, "GPU 温度: %d  ℃", op); 
  u8g2.drawUTF8(0,30,var_buff); 
///////////////////////////////
  sprintf(var_buff, "电脑功耗: %.2f W", qr); 
  u8g2.drawUTF8(0,50,var_buff); 
  u8g2.sendBuffer();
}

void arda64oled()
{
char var_buff[100];
u8g2.clearBuffer();
///////////////////////////////
sprintf(var_buff, "CPU 频率: %d MHZ", ab); 
u8g2.drawUTF8(0,10,var_buff); 
///////////////////////////////
 sprintf(var_buff, "GPU 频率: %d  MHZ", cd); 
  u8g2.drawUTF8(0,20,var_buff); 
///////////////////////////////
  sprintf(var_buff, "CPU 占用率: %3d %%", ef); 
  u8g2.drawUTF8(0,30,var_buff); 
///////////////////////////////
sprintf(var_buff, "GPU 占用率: %3d %%", gh); 
  u8g2.drawUTF8(0,40,var_buff); 
/////////////////////////////
sprintf(var_buff, "运行内存: %3d %%", ij); 
  u8g2.drawUTF8(0,50,var_buff); 
//////////////////////////
  sprintf(var_buff, "显存: %3d %%", kl); 
  u8g2.drawUTF8(0,60,var_buff); 
  u8g2.sendBuffer();
////////////////////////////////////////

}

void arda64()
{
   ard=0;
  if (arda==1)
  {
     ard=1;
    while(Serial.findUntil("a", "b"))
  {
     ab=Serial.parseInt();
     Number1.print(ab);
    //cpu频率
  }
  while(Serial.findUntil("c", "d"))
  {
    //gpu频率
     cd=Serial.parseInt();
     Number2.print(cd);
  }
  while(Serial.findUntil("e", "f"))
  {
    //cpu百分比
     ef=Serial.parseInt();
     Number3.print(ef); 
  }
  while(Serial.findUntil("g", "h"))
  {
    //gpu百分比
       gh=Serial.parseInt();    
       Number4.print(gh); 
  }
  while(Serial.findUntil("i", "j"))
  {
    //内存
       ij=Serial.parseInt(); 
       Number5.print(ij); 
  }
  while(Serial.findUntil("k", "l"))
  {
    //显存
     kl=Serial.parseInt();
    Number6.print(kl); 
  }
    while(Serial.findUntil("m", "n"))
  {
    //cpu温度
     mn=Serial.parseInt();
     Number7.print(mn); 
  }
   while(Serial.findUntil("o", "p"))
  {
    //显卡温度
     op=Serial.parseInt();
     Number8.print(op); 
  }
   while(Serial.findUntil("q", "r"))
  {
    //功耗
     qr=Serial.parseFloat();
     Number9.print(qr); 
  }
  arda=0;
}

}
///////////////////////////
///////////////////////////
//初始化oled
void ShowText(void)
{
  u8g2.begin();
  u8g2.enableUTF8Print(); 
  u8g2.setFont(u8g2_font_wqy12_t_gb2312); //设置字体
  u8g2.clearBuffer();  //清除缓存
  /*u8g2.drawStr(0,10,"Hello World!");  
  u8g2.drawStr(0,20,"This is bro cainiao!");  
  u8g2.drawStr(0,30,"Welcome to U8G2!");  
  u8g2.sendBuffer();  //显示    */
}
///////////////////////////